package com.example.audio;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder.AudioSource;
import android.util.Log;

public class Audio extends Thread {
	
	private boolean stopped;
	private AudioRecord recorder;
	private AudioTrack track;
	private int N;
	private short[][] buffers;
	private int ix;
	private short[] buffer;
	private AudioManager audioManager;

	/***
	 * Main Constructor
	 * @param context, the context where the audio is launched
	 */
	public Audio(Context context)
	{ 
		/*
		 * Give the thread high priority so that it's not canceled unexpectedly, and start it
		 */
		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
	        
	    init(context);
	        
	    start();
	        
	 }
	    
	 /***
	  * Initiate the variables used for the audio part
	  * @param context, the context where the audio is launched
	  */
	 public void init(Context context) {
		 N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);
            
         recorder = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT, N*10);
            
	     track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, N, AudioTrack.MODE_STREAM);
	        
	     stopped = false;
	        
	     audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 
	     
	 }

	 /***
	  * Launch the thread when start() is calling
	  */
	 @SuppressWarnings("deprecation")
	 @Override
	 public void run()
	 { 

		 buffers = new short[100][100];
	     ix = 0;

	      /*
	      * Initialize buffer to hold continuously recorded audio data, start recording, and start
	      * playback.
	      */
	      try
	      {
	    	  recorder.startRecording();
	            
	    	  track.setStereoVolume((float)0.5, (float)0.5);
	            
	    	  track.play();
        	
	          /*
	          * Loops until something outside of this thread stops it.
	          * Reads the data from the recorder and writes it to the audio track for playback.
	          */
	          while(!stopped)
	          {	
	        	  buffer = buffers[ix++ % buffers.length];
	              N = recorder.read(buffer,0,buffer.length);
	              if(audioManager.isWiredHeadsetOn()){
	                track.write(buffer, 0, buffer.length);
	              }
	          }

	       }
	       catch(Throwable x)
	       { 
	           Log.w("Audio", "Error reading voice audio", x);
	       }
	       /*
	        * Frees the thread's resources after the loop completes so that it can be run again
	       */
	       finally
	       { 	
	    	   recorder.stop();
	           recorder.release(); 
	            
	           track.flush();
	           track.stop();
	           track.release();
	       }
        	
	 }

	 /**
	  * Called from outside of the thread in order to stop the recording/playback loop
	  */
	  public void close()
	  { 
	       stopped = true;
	  }
	    
	  /**
	   * Use to set the stereo volume
	   * @param right right volume (0.0 to 1.0)
	   * @param left left volume (0.0 to 1.0)
	  */
	  public void setStereoVolume(float right, float left) {
	    track.setStereoVolume(right, left);
	  }
	    
	  /***
	   * return the audio in stereo corresponding to the ratio given by the video part
	   * @param ratio, the ratio given by the video part (between -1 and 1)
	  */
	  public void returnAudio(float ratio){	
	    if(ratio<-0.3){
	    	track.setStereoVolume(Math.abs(ratio), (float) 0.3);
	    }else if(ratio>0.3){
	    	track.setStereoVolume((float) 0.3, ratio);
	    }else {
	    	track.setStereoVolume((float) 0.5, (float) 0.5);
	    }
	 }
}